/*
 * AnchorToChapterTagger.java
 *
 *  created: 19.8.2011
 *  charset: UTF-8
 *  license: MIT (X11) (See LICENSE file for full license)
 */
package cz.mp.k3bg.core;

import static cz.mp.k3bg.Application.EOL;
import cz.mp.k3bg.log.LoggerManager;
import cz.mp.util.DateUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;
import java.util.logging.Logger;

/**
 * Třída {@code  AnchorToChapterTagger} na začátek každého tagu {@literal <h>}
 * přidá kotvu (cíl odkazu) s pořadovým číslem 
 * ({@literal 
 * <a class="<style_class_jméno>" name="<anchor_prefix><číslo_a>" />}. Kde 
 * 
 * {@literal <anchor_prefix> } je plněno hodnotou {@linkplain #NAME_PREFIX } a
 * {@literal <style_class_jméno> } je plněno 
 *      {@linkplain StyleClassNames#A_TO_H_BASE}).
 * {@literal <číslo_a> } je plněno vnitřním čítačem.
 *      Pořadové číslo v rámci souboru.
 * <p>
 * např:
 * <pre>
 * {@literal <h1>Kapitola 1</h1>  -->  <a class="k3bg_aToH1" name="a_20111124125630_1"><h1>Kapitola 1</h1>}
 * </pre>
 * 
 * @author Martin Pokorný
 * @version 0.1
 */
public class AnchorToChapterTagger {

    private static final boolean DEBUG = false;
    private static final Logger logger =
            LoggerManager.getLogger(AnchorToChapterTagger.class, DEBUG);
    
    
    private BufferedReader srcReader = null;

    private Writer dstWriter = null;
    
    /** Čítač odkazů. */
    private int refCounter = 1;
    
    /** Datum a čas inicializace třídy, ve formátu yyyyMMddHHmmss. */
    static final String DATE_FULL = 
            DateUtils.getCurrentDate("yyyyMMddHHmmss");
    
    /** Text ve formátu "{@literal a_<datum_ve_formatu_yyyyMMddHHmmss>_}". */
    public static final String NAME_PREFIX = "a_" + DATE_FULL + "_";
    
    // -----

    /**
     * 
     * @param srcReader
     * @param dstWriter 
     * @throws IllegalArgumentException
     */
    public AnchorToChapterTagger(
            BufferedReader srcReader, Writer dstWriter) {
        logger.fine("");
        if (srcReader == null) {
            throw new IllegalArgumentException("srcReader=null");
        }
        this.srcReader = srcReader;
        
        if (dstWriter == null) {
            throw new IllegalArgumentException("dstWriter=null");
        }
        this.dstWriter = dstWriter;        
    }

    // -----
    
    /**
     * 
     * @return 
     */
    public BufferedReader getSrcReader() {
        return srcReader;
    }

    /**
     * 
     * @return 
     */
    public Writer getDstWriter() {
        return dstWriter;
    }

    /**
     * 
     * @return 
     */
    public int getRefCounter() {
        return refCounter;
    }

    /**
     * 
     * @param refCounter 
     */
    public void setRefCounter(int refCounter) {
        this.refCounter = refCounter;
    }
    
    /**
     * 
     * @throws IOException 
     */
    public void process() throws IOException {
        logger.info("");
        String line = "";
        while ((line = srcReader.readLine()) != null) {
            line = processLine(line);

            writeLine(line);
        }
        
        close();
        logger.fine("(finished!)");
    }
 
    /**
     * Před každý text {@literal "<h[čísloH]"} vloží 
     * {@literal <a class="aToH[čísloH]" name=a_[datumčas]_[čísloA] />"}
     * 
     * @param line
     * @return 
     */
    private String processLine(String line) {
        String newLine = line;
        
        String[] hParts = newLine.split("<[hH]");
        
        if (hParts.length > 1) {
            StringBuilder newLineBuilder = new StringBuilder();            
            for (int i=0; i<hParts.length; i++) {
                if (hParts[i].length() > 0) {        
                    // <h1 vs <html   (hParts[i].charAt(0) =  1 vs t
                    if (! Character.isDigit(hParts[i].charAt(0))) {
                        return line;
                    }
                    
                    int hLevel = Integer.parseInt(hParts[i].substring(0, 1));                    
                    hParts[i] = 
                            createAnchor(hLevel, NAME_PREFIX, refCounter)
                            + "<h" + hParts[i];
                    refCounter++;
                }
                newLineBuilder.append(hParts[i]);
            } 
            newLine = newLineBuilder.toString();
            logger.finer(newLine);
        }
        
        return newLine;
    }    
    
    /**
     * Sestaví značku s kotvou ve formátu
     * {@literal <a class="aToH[čísloH]" name=a_[datumčas]_[pořadovéČísloA] />"}
     * <p>
     * např:
     * {@literal <a class="aToH1" name=a_20110822123010_15" />}
     * 
     * @param hLevel
     * @param name
     * @param number
     * @return 
     */
    private String createAnchor(int hLevel, String name, int number) {
        logger.finest("hLevel = " + hLevel 
                + "  name = " + name 
                + "  number = " + number);
        StringBuilder sb = new StringBuilder();
        sb.append("<a ").append("class=\"")
                .append(StyleClassNames.A_TO_H_BASE.getRealName()).append(hLevel)
                .append("\" ").append("name=\"")
                .append(name).append(number)
                .append("\" />");
        return sb.toString();
    }
    
    /**
     * Zavře "dokončené proudy".
     * 
     * @throws IOException 
     */
    private void close() throws IOException {
        logger.fine("");
        if (srcReader != null)  {
            srcReader.close();
        }
        if (dstWriter != null) {
            dstWriter.close();
        }
    }

    /**
     * 
     * @param line
     * @throws IOException 
     */
    private void writeLine(String line) throws IOException {
        dstWriter.write(line);
        dstWriter.write(EOL);
        dstWriter.flush();
    }
    
}   // AnchorToChapterTagger
